#pragma once 
#include"const.h"
#include"message.grpc.pb.h"
#include"message.pb.h"
#include<grpc++/grpc++.h>
#include"Singleton.h"
#include"ConFigMgr.h"

using grpc::Channel;
using grpc::Status;
using grpc::ClientContext;

using message::AddFriendReq;
using message::AddFriendRsp;

using message::GetChatServerRsp;
using message::LoginRsp;
using message::LoginReq;
using message::ChatService;

class ChatConPool {
public:
	ChatConPool(size_t poolsize,std::string host,std::string port):
		_poolsize(poolsize),_host(host),_port(port){
		for (int i = 0; i < poolsize; ++i) {
			std::shared_ptr<Channel> channl_ = grpc::CreateChannel(host + ":" + port, grpc::InsecureChannelCredentials());
			_connections.push(ChatService::NewStub(channl_));
		}
	}

	~ChatConPool() {
		std::lock_guard<std::mutex> lock(_mutex);
		Close();
		while (!_connections.empty())
		{
			_connections.pop();
		}
	}
	
	void Close() {
		_b_stop = true;
		_cond.notify_all();
	}

	std::unique_ptr<ChatService::Stub> getConnection() {
		std::unique_lock<std::mutex> lock(_mutex);
		_cond.wait(lock,[this] {
			if (_b_stop)
			{
				return true;
			}

			return !_connections.empty();
			});

		if (_b_stop)
		{
			return nullptr;
		}

		std::unique_ptr<ChatService::Stub> temp = std::move(_connections.front());
		_connections.pop();
		return temp;
	}

	void retrunConnectin(std::unique_ptr<ChatService::Stub> stub_) {
		std::unique_lock<std::mutex> lock(_mutex);
		if (_b_stop) {
			return;
		}
		_connections.push(std::move(stub_));
		_cond.notify_one();
	}
private:
	size_t _poolsize;
	std::string _host;
	std::string _port;
	atomic<bool> _b_stop;
	std::mutex _mutex;
	std::queue<std::unique_ptr<ChatService::Stub> > _connections;
	condition_variable _cond;

};


class ChatGrpcClient:public Singleton<ChatGrpcClient>
{
	friend class Singleton<ChatGrpcClient>;
public:
	~ChatGrpcClient() {};

	AddFriendRsp NotifyAddFriend(const AddFriendReq& req);


private:
	ChatGrpcClient();

	std::unordered_map<std::string, std::unique_ptr<ChatConPool>> _pools;
};

